﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TempMonitor
{
    public partial class calibration : Form
    {
        public calibration()
        {
            InitializeComponent();
        }
        byte deviceAddr = 0;
        const byte writeHoldingRegisterResponseDataLength = 8;
        private bool isNumber(string s)
        {
            char[] str = s.ToCharArray();
            for (int i = 0; i < str.Length; i++)
            {
                if (Char.IsNumber(str[i]) == false)
                {
                    return false;
                }
            }
            return true;
        }

        private bool OpenSerial()
        {
            if (!serialPort1.IsOpen)
            {
                try
                {
                    string portName = modbus.PortName;
                    if (portName != "")
                    {
                        //串口的设置
                        serialPort1.PortName = portName;
                        serialPort1.BaudRate = 9600;
                        serialPort1.Parity = Parity.None;
                        serialPort1.DataBits = 8;
                        serialPort1.StopBits = StopBits.One;

                        serialPort1.Open();
                    }
                    else
                    {
                        this.Invoke(new Action(() =>
                        {
                            label7.Text = "串口未选择";
                        }));
                        Log.WriteLog("串口未选择:");
                        return false;
                    }
                }
                catch (Exception msg)
                {
                    this.Invoke(new Action(() =>
                    {
                        label7.Text = msg.Message;
                    }));
                    Log.WriteLog("打开串口异常:");
                    Log.WriteLog(msg.Message);
                    Log.WriteLog(msg.StackTrace);
                    serialPort1.Close();
                    return false;
                }
            }
            Log.WriteLog("串口已打开。");
            this.Invoke(new Action(() =>
            {
                label7.Text = "串口已打开。";
            }));
            return true;
        }

        private bool SendWriteHoldingRegisterDataAndVerify(byte[] sendData, UInt16 registerStartAddr, UInt16 registerCount)
        {
            serialPort1.ReadExisting();//清空缓存
            serialPort1.Write(sendData, 0, sendData.Length);

            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(100);
                int len = serialPort1.BytesToRead;
                if (len >= writeHoldingRegisterResponseDataLength)
                {
                    byte[] recData = new byte[len];
                    serialPort1.Read(recData, 0, len);

                    UInt16 crc = modbus.Get_Crc_16(recData, writeHoldingRegisterResponseDataLength - 2);
                    UInt16 crcData = (UInt16)(recData[writeHoldingRegisterResponseDataLength - 1] + recData[writeHoldingRegisterResponseDataLength - 2] * 256);
                    if (crc != crcData)
                    {
                        string tmp = string.Format("CRC:{0:X},CRC check:{0:X}", crcData, crc);
                        Log.WriteLog("返回的CRC不对--" + tmp);
                        return false;
                    }
                    if (recData[0] != deviceAddr || recData[1] != modbus.WriteMultipleRegister)
                    {
                        Log.WriteLog("返回的设备地址或者功能码不对。");
                        return false;
                    }
                    UInt16 startAddr = (UInt16)(recData[2] * 256 + recData[3]);
                    if (startAddr != registerStartAddr)
                    {
                        Log.WriteLog("返回的设备起始地址不对。");
                        return false;
                    }
                    UInt16 regCount = (UInt16)(recData[4] * 256 + recData[5]);
                    if (regCount != registerCount)
                    {
                        Log.WriteLog("返回的寄存器数量不对。");
                        return false;
                    }
                    return true;
                }
            }

            return false;
        }

        private bool SendReadInputRegisterDataAndVerify(byte[] sendData, UInt16 registerStartAddr, UInt16 registerCount, ref byte recDataLen, ref byte[] receiveData)
        {
            serialPort1.ReadExisting();//清空缓存
            serialPort1.Write(sendData, 0, sendData.Length);

            /* 返回的数据
             * 从机地址	 功能号	数据字节个数(1字节)	字节数据(寄存器先发送的先回来)	CRC校验 */
            int receiveDataLength = 5 + registerCount * 2;

            for (int i = 0; i < (2 + registerCount); i++)
            {
                Thread.Sleep(100);
                int len = serialPort1.BytesToRead;
                if (len >= receiveDataLength)
                {
                    byte[] readData = new byte[len];
                    serialPort1.Read(readData, 0, len);

                    UInt16 crc = modbus.Get_Crc_16(readData, receiveDataLength - 2);
                    UInt16 crcData = (UInt16)(readData[receiveDataLength - 1] + readData[receiveDataLength - 2] * 256);
                    if (crc != crcData)
                    {
                        string tmp = string.Format("CRC:{0:X},CRC check:{0:X}", crcData, crc);
                        Log.WriteLog("返回的CRC不对--" + tmp);
                        return false;
                    }
                    if (readData[0] != deviceAddr || readData[1] != modbus.ReadInputRegister)
                    {
                        Log.WriteLog("返回的设备地址或者功能码不对。");
                        return false;
                    }
                    recDataLen = readData[2];
                    Array.Copy(readData, 3, receiveData, 0, recDataLen);
                    return true;
                }
            }

            return false;
        }


        private bool SendReadHoldingRegisterDataAndVerify(byte[] sendData, UInt16 registerStartAddr, UInt16 registerCount, ref byte recDataLen, ref byte[] receiveData)
        {
            serialPort1.ReadExisting();//清空缓存
            serialPort1.Write(sendData, 0, sendData.Length);

            /* 返回的数据
             * 从机地址	 功能号	数据字节个数(1字节)	字节数据(寄存器先发送的先回来)	CRC校验 */
            int receiveDataLength = 5 + registerCount * 2;

            for (int i = 0; i < (2 + registerCount); i++)
            {
                Thread.Sleep(100);
                int len = serialPort1.BytesToRead;
                if (len >= receiveDataLength)
                {
                    byte[] readData = new byte[len];
                    serialPort1.Read(readData, 0, len);

                    UInt16 crc = modbus.Get_Crc_16(readData, receiveDataLength - 2);
                    UInt16 crcData = (UInt16)(readData[receiveDataLength - 1] + readData[receiveDataLength - 2] * 256);
                    if (crc != crcData)
                    {
                        string tmp = string.Format("CRC:{0:X},CRC check:{0:X}", crcData, crc);
                        Log.WriteLog("返回的CRC不对--" + tmp);
                        return false;
                    }
                    if (readData[0] != deviceAddr || readData[1] != modbus.ReadHoldingRegister)
                    {
                        Log.WriteLog("返回的设备地址或者功能码不对。");
                        return false;
                    }
                    recDataLen = readData[2];
                    Array.Copy(readData, 3, receiveData, 0, recDataLen);
                    return true;
                }
            }

            return false;
        }

        private void calibration_Load(object sender, EventArgs e)
        {
            deviceAddr = modbus.DeviceAddr;
            label5.Text = "当前设备地址：" + deviceAddr.ToString();
            label4.Text = "选择串口：" + modbus.PortName;
        }

        private bool ReadTempFromDevice(ref UInt16 temp)
        {
            const UInt16 registerStartAddr = 99;
            Log.WriteLog("开始从设备里读取实时温度。");
            byte[] data = modbus.GetDataForReadInputRegister(deviceAddr, registerStartAddr, 1);
            byte[] receiveData = new byte[2]; //只有2个字节
            byte receiveDataLength = 0;
            bool returnValue = SendReadInputRegisterDataAndVerify(data, registerStartAddr, 1, ref receiveDataLength, ref receiveData);
            if (returnValue == true && receiveDataLength == 2)
            {
                temp = (UInt16)(receiveData[0] * 256 + receiveData[1]);
                Log.WriteLog("设备实时温度ADC是:" + temp.ToString());
            }
            else
            {
                Log.WriteLog("读取设备实时温度：数据长度不对或没有收到数据。");
                return false;
            }
            return returnValue;
        }

        private bool ReadCalibrationDatasFromDevice(ref UInt16[] temp)
        {
            UInt16 registerStartAddr = 17;
            Log.WriteLog("开始从设备里读取读取5个校准寄存器数据。");
            byte[] data = modbus.GetDataForReadHoldingRegister(deviceAddr, registerStartAddr, 5);
            byte[] receiveData = new byte[10]; //只有10个字节
            byte receiveDataLength = 0;
            bool returnValue = SendReadHoldingRegisterDataAndVerify(data, registerStartAddr, 5, ref receiveDataLength, ref receiveData);
            if (returnValue == true && receiveDataLength == 10)
            {
                temp[0] = (UInt16)(receiveData[0] * 256 + receiveData[1]);
                temp[1] = (UInt16)(receiveData[2] * 256 + receiveData[3]);
                temp[2] = (UInt16)(receiveData[4] * 256 + receiveData[5]);
                temp[3] = (UInt16)(receiveData[6] * 256 + receiveData[7]);
                temp[4] = (UInt16)(receiveData[8] * 256 + receiveData[9]);
                Log.WriteLog("读取5个校准寄存器数据：" + temp[0].ToString() + "" + temp[1].ToString() + "" + temp[2].ToString() + "" + temp[3].ToString() + "" + temp[4].ToString());
            }
            else
            {
                Log.WriteLog("读取5个校准寄存器数据：数据长度不对或没有收到数据。");
                return false;
            }
            return returnValue;
        }

        private bool ReadCalibrationFromDevice(ref UInt16 temp, UInt16 registerStartAddr)
        {
            Log.WriteLog("开始从设备里读取校准寄存器数据。");
            byte[] data = modbus.GetDataForReadHoldingRegister(deviceAddr, registerStartAddr, 1);
            byte[] receiveData = new byte[2]; //只有2个字节
            byte receiveDataLength = 0;
            bool returnValue = SendReadHoldingRegisterDataAndVerify(data, registerStartAddr, 1, ref receiveDataLength, ref receiveData);
            if (returnValue == true && receiveDataLength == 2)
            {
                temp = (UInt16)(receiveData[0] * 256 + receiveData[1]);
            }
            else
            {
                Log.WriteLog("读取读取校准寄存器数据：数据长度不对或没有收到数据。");
                return false;
            }
            return returnValue;
        }

        private bool SetCalibrationToDevice(UInt16 registerStartAddr, UInt16 temp)
        {
            byte[] data = new byte[2];
            data[0] = (byte)(temp >> 8);//高位
            data[1] = (byte)(temp & 0xff);
            Log.WriteLog("设置校验寄存器：" + registerStartAddr.ToString() + "数据：" + data[0].ToString() + " " + data[1].ToString()) ;
            byte[] sendData = modbus.GetDataForWriteHoldingRegister(deviceAddr, registerStartAddr, 1, 2, data);
            if (SendWriteHoldingRegisterDataAndVerify(sendData, registerStartAddr, 1) == true)
            {
                Thread.Sleep(500);
                UInt16 tempReadFromDevice = 0;
                if (ReadCalibrationFromDevice(ref tempReadFromDevice, registerStartAddr) == true)
                {
                    if (temp == tempReadFromDevice)
                    {
                        Log.WriteLog("设置校验寄存器：成功。");
                        label7.Text = "设置校验寄存器：成功！";
                        return true;
                    }
                    else
                    {
                        label7.Text = "回读校准寄存器不一致！";
                        Log.WriteLog("回读校准寄存器不一致。");
                    }
                }
                else
                {
                    label7.Text = "读取校验寄存器出错！";
                    Log.WriteLog("读取校验寄存器出错。");
                }
            }
            label7.Text = "设置校验寄存器：出错！";
            Log.WriteLog("设置校验寄存器：出错。");
            return false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (OpenSerial() == true)
                {
                    label7.Text = "正在读取设备，请稍候...";
                    UInt16 temp = 0;

                    if (ReadTempFromDevice(ref temp) == true)
                    {
                        textBox1.Text = temp.ToString();
                        label7.Text = "成功读取到数据。";
                    }
                    else
                    {
                        label7.Text = "无法读取到数据。";
                    }
                    Thread.Sleep(500);
                    UInt16[] calibra = new UInt16[5];
                    if(ReadCalibrationDatasFromDevice(ref calibra) == true)
                    {
                        textBox5.Text = calibra[0].ToString();
                        textBox9.Text = calibra[1].ToString();
                        textBox11.Text = calibra[2].ToString();
                        textBox6.Text = calibra[3].ToString();
                        textBox7.Text = calibra[4].ToString();
                    }
                    else
                    {
                        label7.Text = "无法读取到校准数据。";
                    }
                    serialPort1.Close();
                    
                }
                else
                {
                    Log.WriteLog("打开串口出错！");
                    label7.Text = "打开串口出错！";
                    serialPort1.Close();
                }
            }
            catch (Exception ex)
            {
                Log.WriteLog(ex.Message);
                Log.WriteLog(ex.StackTrace);
                serialPort1.Close();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            UInt16 registerStartAddr = 17;
            if (textBox2.Text.Trim() != "")
            {
                 try
                {
                    if (OpenSerial() == true)
                    {
                        Log.WriteLog("设置-20度校验寄存器--数据：" + textBox2.Text);
                        UInt16 temp = Convert.ToUInt16(textBox2.Text.Trim());
                        if (SetCalibrationToDevice(registerStartAddr, temp) == true)
                        {
                            label7.Text = "成功写入-20度校准寄存器！";
                            textBox5.Text = textBox2.Text;
                        }
                        else
                        {
                            label7.Text = "写入-20度校准寄存器出错！";
                            Log.WriteLog("写入-20度校准寄存器出错！");
                        }
                        serialPort1.Close();
                    }
                    else
                    {
                        Log.WriteLog("打开串口出错！");
                        label7.Text = "打开串口出错！";
                        serialPort1.Close();
                    }
                }
                catch(Exception ex)
                {
                    label7.Text = ex.Message;
                    serialPort1.Close();
                }
            
            }
            else
            {
                label7.Text = "请输入数字！";
            }
            
        }

        private void button3_Click(object sender, EventArgs e)
        {
            UInt16 registerStartAddr = 20;
            if (textBox3.Text.Trim() != "")
            {
                try
                {
                    if (OpenSerial() == true)
                    {
                        Log.WriteLog("设置80度校验寄存器--数据：" + textBox3.Text);
                        UInt16 temp = Convert.ToUInt16(textBox3.Text.Trim());
                        if (SetCalibrationToDevice(registerStartAddr, temp) == true)
                        {
                            label7.Text = "成功写入80度校准寄存器！";
                            textBox6.Text = textBox3.Text;
                        }
                        else
                        {
                            label7.Text = "写入80度校准寄存器出错！";
                            Log.WriteLog("写入80度校准寄存器出错！");
                        }
                        serialPort1.Close();
                    }
                    else
                    {
                        Log.WriteLog("打开串口出错！");
                        label7.Text = "打开串口出错！";
                        serialPort1.Close();
                    }
                }
                catch (Exception ex)
                {
                    label7.Text = ex.Message;
                    serialPort1.Close();
                }

            }
            else
            {
                label7.Text = "请输入数字！";
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            UInt16 registerStartAddr = 21;
            if (textBox4.Text.Trim() != "")
            {
                try
                {
                    if (OpenSerial() == true)
                    {
                        Log.WriteLog("设置120度校验寄存器--数据：" + textBox4.Text);
                        UInt16 temp = Convert.ToUInt16(textBox4.Text.Trim());
                        if (SetCalibrationToDevice(registerStartAddr, temp) == true)
                        {
                            label7.Text = "成功写入120度校准寄存器！";
                            textBox7.Text = textBox4.Text;
                        }
                        else
                        {
                            label7.Text = "写入120度校准寄存器出错！";
                            Log.WriteLog("写入120度校准寄存器出错！");
                        }
                        serialPort1.Close();
                    }
                    else
                    {
                        Log.WriteLog("打开串口出错！");
                        label7.Text = "打开串口出错！";
                        serialPort1.Close();
                    }
                }
                catch (Exception ex)
                {
                    label7.Text = ex.Message;
                    serialPort1.Close();
                }

            }
            else
            {
                label7.Text = "请输入数字！";
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            UInt16 registerStartAddr = 18;
            if (textBox8.Text.Trim() != "")
            {
                try
                {
                    if (OpenSerial() == true)
                    {
                        Log.WriteLog("设置0度校验寄存器--数据：" + textBox8.Text);
                        UInt16 temp = Convert.ToUInt16(textBox8.Text.Trim());
                        if (SetCalibrationToDevice(registerStartAddr, temp) == true)
                        {
                            label7.Text = "成功写入0度校准寄存器！";
                            textBox9.Text = textBox8.Text;
                        }
                        else
                        {
                            label7.Text = "写入0度校准寄存器出错！";
                            Log.WriteLog("写入0度校准寄存器出错！");
                        }
                        serialPort1.Close();
                    }
                    else
                    {
                        Log.WriteLog("打开串口出错！");
                        label7.Text = "打开串口出错！";
                        serialPort1.Close();
                    }
                }
                catch (Exception ex)
                {
                    label7.Text = ex.Message;
                    serialPort1.Close();
                }

            }
            else
            {
                label7.Text = "请输入数字！";
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            UInt16 registerStartAddr = 19;
            if (textBox10.Text.Trim() != "")
            {
                try
                {
                    if (OpenSerial() == true)
                    {
                        Log.WriteLog("设置40度校验寄存器--数据：" + textBox10.Text);
                        UInt16 temp = Convert.ToUInt16(textBox10.Text.Trim());
                        if (SetCalibrationToDevice(registerStartAddr, temp) == true)
                        {
                            label7.Text = "成功写入40度校准寄存器！";
                            textBox11.Text = textBox10.Text;
                        }
                        else
                        {
                            label7.Text = "写入40度校准寄存器出错！";
                            Log.WriteLog("写入40度校准寄存器出错！");
                        }
                        serialPort1.Close();
                    }
                    else
                    {
                        Log.WriteLog("打开串口出错！");
                        label7.Text = "打开串口出错！";
                        serialPort1.Close();
                    }
                }
                catch (Exception ex)
                {
                    label7.Text = ex.Message;
                    serialPort1.Close();
                }

            }
            else
            {
                label7.Text = "请输入数字！";
            }
        }
    }


}
